package com.ruoyi.project.system.controller

import com.ruoyi.common.constant.UserConstants
import com.ruoyi.common.utils.*
import com.ruoyi.common.utils.poi.ExcelUtil
import com.ruoyi.framework.aspectj.lang.annotation.*
import com.ruoyi.framework.aspectj.lang.enums.BusinessType
import com.ruoyi.framework.web.controller.BaseController
import com.ruoyi.framework.web.domain.AjaxResult
import com.ruoyi.framework.web.page.TableDataInfo
import com.ruoyi.project.system.domain.SysDept
import com.ruoyi.project.system.domain.SysRole
import com.ruoyi.project.system.domain.SysUser
import com.ruoyi.project.system.domain.SysUser.Companion.isAdmin
import com.ruoyi.project.system.service.ISysDeptService
import com.ruoyi.project.system.service.ISysPostService
import com.ruoyi.project.system.service.ISysRoleService
import com.ruoyi.project.system.service.ISysUserService
import org.apache.commons.lang3.ArrayUtils
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.MultipartFile
import java.util.stream.Collectors
import javax.servlet.http.HttpServletResponse

/**
 * 用户信息
 *
 * @author ruoyi
 */
@RestController
@RequestMapping("/system/user")
open class SysUserController : BaseController() {
    @Autowired
    private val userService: ISysUserService? = null

    @Autowired
    private val roleService: ISysRoleService? = null

    @Autowired
    private val deptService: ISysDeptService? = null

    @Autowired
    private val postService: ISysPostService? = null

    /**
     * 获取用户列表
     */
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/list")
    fun list(user: SysUser?): TableDataInfo {
        startPage()
        val list = userService!!.selectUserList(user)
        return getDataTable(list)
    }

    @Log(title = "用户管理", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:user:export')")
    @PostMapping("/export")
    fun export(response: HttpServletResponse, user: SysUser?) {
        val list = userService!!.selectUserList(user)
        val util = ExcelUtil(SysUser::class.java)
        util.exportExcel(response, list, "用户数据")
    }

    @Log(title = "用户管理", businessType = BusinessType.IMPORT)
    @PreAuthorize("@ss.hasPermi('system:user:import')")
    @PostMapping("/importData")
    @Throws(
        Exception::class
    )
    fun importData(file: MultipartFile, updateSupport: Boolean): AjaxResult {
        val util = ExcelUtil(SysUser::class.java)
        val userList = util.importExcel(file.inputStream)
        val operName = username
        val message = userService!!.importUser(userList, updateSupport, operName)
        return AjaxResult.Companion.success(message)
    }

    @PostMapping("/importTemplate")
    fun importTemplate(response: HttpServletResponse?) {
        val util = ExcelUtil(SysUser::class.java)
        util.importTemplateExcel(response!!, "用户数据")
    }

    /**
     * 根据用户编号获取详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping(value = ["/", "/{userId}"])
    fun getInfo(@PathVariable(value = "userId", required = false) userId: Long?): AjaxResult {
        userService!!.checkUserDataScope(userId)
        val ajax: AjaxResult = AjaxResult.success()
        val roles = roleService!!.selectRoleAll()
        ajax["roles"] =
            if (isAdmin(userId)) roles else roles!!.stream().filter { r: SysRole -> !r.isAdmin }
                .collect(Collectors.toList())
        ajax["posts"] = postService!!.selectPostAll()
        if (StringUtils.isNotNull(userId)) {
            val sysUser = userService.selectUserById(userId)
            ajax[AjaxResult.DATA_TAG] = sysUser
            ajax["postIds"] = postService.selectPostListByUserId(userId)
            ajax["roleIds"] = sysUser!!.roles!!.stream().map { obj: SysRole -> obj.roleId }.collect(Collectors.toList())
        }
        return ajax
    }

    /**
     * 新增用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:add')")
    @Log(title = "用户管理", businessType = BusinessType.INSERT)
    @PostMapping
    fun add(@Validated @RequestBody user: SysUser): AjaxResult {
        if (UserConstants.NOT_UNIQUE == userService!!.checkUserNameUnique(user.userName)) {
            return AjaxResult.Companion.error("新增用户'" + user.userName + "'失败，登录账号已存在")
        } else if (StringUtils.isNotEmpty(user.phonenumber) && UserConstants.NOT_UNIQUE == userService.checkPhoneUnique(
                user
            )
        ) {
            return AjaxResult.Companion.error("新增用户'" + user.userName + "'失败，手机号码已存在")
        } else if (StringUtils.isNotEmpty(user.email) && UserConstants.NOT_UNIQUE == userService.checkEmailUnique(user)) {
            return AjaxResult.Companion.error("新增用户'" + user.userName + "'失败，邮箱账号已存在")
        }
        user.createBy = username
        user.password = SecurityUtils.encryptPassword(user.password)
        return toAjax(userService.insertUser(user))
    }

    /**
     * 修改用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping
    fun edit(@Validated @RequestBody user: SysUser): AjaxResult {
        userService!!.checkUserAllowed(user)
        userService.checkUserDataScope(user.userId)
        if (StringUtils.isNotEmpty(user.phonenumber) && UserConstants.NOT_UNIQUE == userService.checkPhoneUnique(user)) {
            return AjaxResult.Companion.error("修改用户'" + user.userName + "'失败，手机号码已存在")
        } else if (StringUtils.isNotEmpty(user.email) && UserConstants.NOT_UNIQUE == userService.checkEmailUnique(user)) {
            return AjaxResult.Companion.error("修改用户'" + user.userName + "'失败，邮箱账号已存在")
        }
        user.updateBy = username
        return toAjax(userService.updateUser(user))
    }

    /**
     * 删除用户
     */
    @PreAuthorize("@ss.hasPermi('system:user:remove')")
    @Log(title = "用户管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{userIds}")
    fun remove(@PathVariable userIds: Array<Long?>): AjaxResult {
        return if (ArrayUtils.contains(userIds, userId)) {
            error("当前用户不能删除")
        } else toAjax(userService!!.deleteUserByIds(userIds))
    }

    /**
     * 重置密码
     */
    @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/resetPwd")
    fun resetPwd(@RequestBody user: SysUser): AjaxResult {
        userService!!.checkUserAllowed(user)
        userService.checkUserDataScope(user.userId)
        user.password = SecurityUtils.encryptPassword(user.password)
        user.updateBy = username
        return toAjax(userService.resetPwd(user))
    }

    /**
     * 状态修改
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    fun changeStatus(@RequestBody user: SysUser): AjaxResult {
        userService!!.checkUserAllowed(user)
        userService.checkUserDataScope(user.userId)
        user.updateBy = username
        return toAjax(userService.updateUserStatus(user))
    }

    /**
     * 根据用户编号获取授权角色
     */
    @PreAuthorize("@ss.hasPermi('system:user:query')")
    @GetMapping("/authRole/{userId}")
    fun authRole(@PathVariable("userId") userId: Long?): AjaxResult {
        val ajax: AjaxResult = AjaxResult.success()
        val user = userService!!.selectUserById(userId)
        val roles = roleService!!.selectRolesByUserId(userId)
        ajax["user"] = user
        ajax["roles"] = if (isAdmin(userId)) roles else roles.filter { r: SysRole -> !r.isAdmin }
        return ajax
    }

    /**
     * 用户授权角色
     */
    @PreAuthorize("@ss.hasPermi('system:user:edit')")
    @Log(title = "用户管理", businessType = BusinessType.GRANT)
    @PutMapping("/authRole")
    fun insertAuthRole(userId: Long?, roleIds: Array<Long>): AjaxResult {
        userService!!.checkUserDataScope(userId)
        userService.insertUserAuth(userId, roleIds)
        return success()
    }

    /**
     * 获取部门树列表
     */
    @PreAuthorize("@ss.hasPermi('system:user:list')")
    @GetMapping("/deptTree")
    fun deptTree(dept: SysDept?): AjaxResult {
        return AjaxResult.success(deptService!!.selectDeptTreeList(dept))
    }
}
